#ifndef __ASTRAL_H_
#define __ASTRAL_H_

/******************************************************************************
This header file is used to:

Define the object struct used in Astral Operating System.

*******************************************************************************/

#include "typedef.h"
#include "queuedef.h"


typedef enum AstralTaskStatus
{
    BLOCKED = 0x10,
    FINISH,
    READY = 0x20,
    RUNNING,
    RUNNING1,
    RUNNING2,
    CREATED,
    RESUMED,
    PREEMPTED,
    SLICEUP
} AstralTaskStatus;

typedef enum SchedMethod{
    FIFO,
    PRIO
} SchedMethod;

typedef struct AstralAttr
{
    StackPointer base;
    int stack_size;
    int priority;
    const char *name;
    SchedMethod method;
} *AstralAttr;

typedef struct AstralTask
{
    void *ksp;
    void *ksp_top;
    void *ksp_bot;

    void *usp;
    void *usp_top;
    void *usp_bot;

    unsigned id;
    unsigned priority;
    unsigned run_times;
    unsigned affinity;
    unsigned core;

    unsigned slice;
    unsigned slice_work;

#define KTASK (0)
#define UTASK (1)

    runable entry;
    object param;
    AstralTaskStatus status;
    boolean  released; //means that this task is released by the running core
    SchedMethod method;
    char name[15];

    struct AstralTask *parent;
    struct Queue childs;
    struct QueueNode tree;
    struct QueueNode sus_on;
    unsigned task_type;
} *AstralTask;

#define DEFINE_TASK(varname) \
        struct AstralTask varname##_ins; \
        AstralTask varname = &varname##_ins;


typedef struct AstralTickTimer
{
    int id;
    int timeout;
    boolean is_oneshot;
    executable callback;
    object arg;
} *AstralTickTimer;

typedef struct AstralMutex
{
    unsigned id;
    unsigned ref_cnt;
    AstralTask owner;
    AstralTask player;
} *AstralMutex;

typedef struct AstralSem
{
    unsigned id;
    unsigned value;
    AstralTask player;
} *AstralSem;

typedef struct AstralSpin
{
   volatile unsigned lock;
} *AstralSpin;



struct PoolJob
{
    runable entry;
    object arg;
    int ret;
    enum {
        DONE,
        VALID,
    } status;
};

struct PoolWoker
{
    struct AstralTask thread;
    address init_sp;
};

typedef struct AstralTaskPool
{
    int nr_thread;
    word player;
    int ppointer;
    int gpointer;
    struct AstralSem psem;
    struct AstralSem gsem;
    struct {
        struct PoolJob job;
        struct PoolWoker worker;
    } job_workers[0];
} *AstralTaskPool;

typedef struct AstralDevice
{
    struct AstralDriver *operations;
    char name[10];
    address pbase;
    address vbase;
    int irq;
    enum
    {
        REGISTERED,
        OPENED,
        CLOSED
    } status;
    struct QueueNode reged;
} *AstralDevice;

typedef struct AstralDriver
{
    unsigned mid;
    int (*dread)(AstralDevice, char *, int, int *);
    int (*dwrite)(AstralDevice, const char *, int, int *);
    int (*dopen)(AstralDevice, object);
    int (*dclose)(AstralDevice, object);
    int (*dcontrol)(AstralDevice, int, int);
    void (*derror)(AstralDevice, int);
    const char *description;

    char smid[17];
    struct QueueNode reged; //registered node
} *AstralDriver;

typedef struct AstralDevInfo
{
    char name[10];
    address base;
    int irq;
    u32 mid;
} *AstralDevInfo;

#define SREGIDEV(b, i, n, m)                   \
    struct AstralDevInfo _dev_##n              \
        __attribute__((section("devtable"))) = \
            {.base = CAST_AS(address, b),      \
             .irq = i,                         \
             .name = #n,                       \
             .mid = m};

#define MIDv4a(mid) ((mid >> 24) & 0xff)
#define MIDv4b(mid) ((mid >> 16) & 0xff)
#define MIDv4c(mid) ((mid >> 8) & 0xff)
#define MIDv4d(mid) ((mid >> 0) & 0xff)
#define MIDv4(a, b, c, d) (a << 24 | b << 16 | c << 8 | d)

#endif//__ASTRAL_H_